package com.jinbaoty.recyclebins;

import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.util.Log;

import androidx.annotation.NonNull;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.idescout.sql.SqlScoutServer;
import com.jinbaoty.recyclebins.command.CommandOrder;
import com.jinbaoty.recyclebins.command.CommandParam;
import com.jinbaoty.recyclebins.command.UsbPortUtils;
import com.jinbaoty.recyclebins.server.APIService;
import com.jinbaoty.recyclebins.server.AlarmService;
import com.jinbaoty.recyclebins.server.ResponseData;
import com.jinbaoty.recyclebins.server.update.OKHttpUpdateHttpService;
import com.jinbaoty.recyclebins.utils.AlarmManagerUtils;
import com.jinbaoty.recyclebins.utils.GetDeviceId;
import com.kongzue.dialog.util.DialogSettings;
import com.kongzue.dialog.v3.TipDialog;
import com.orhanobut.logger.AndroidLogAdapter;
import com.orhanobut.logger.Logger;
import com.wanjian.sak.SAK;
import com.wanjian.sak.config.Config;
import com.xuexiang.xpage.PageConfig;
import com.xuexiang.xpage.PageConfiguration;
import com.xuexiang.xpage.model.PageInfo;
import com.xuexiang.xui.XUI;
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog;
import com.xuexiang.xupdate.XUpdate;
import com.xuexiang.xupdate.entity.DownloadEntity;
import com.xuexiang.xupdate.entity.UpdateError;
import com.xuexiang.xupdate.listener.OnInstallListener;
import com.xuexiang.xupdate.listener.OnUpdateFailureListener;
import com.xuexiang.xupdate.utils.UpdateUtils;
import com.xuexiang.xutil.XUtil;
import com.xuexiang.xutil.common.StringUtils;
import com.xuexiang.xutil.system.PermissionUtils;
import com.xuexiang.xutil.tip.ToastUtils;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.callback.StringCallback;

import org.xutils.BuildConfig;
import org.xutils.DbManager;
import org.xutils.x;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

import cn.hutool.core.util.StrUtil;
import okhttp3.Call;
import okhttp3.OkHttpClient;

import static com.xuexiang.xupdate.entity.UpdateError.ERROR.CHECK_NO_NEW_VERSION;

public class MyApplication extends Application {
    public static DbManager.DaoConfig daoConfig;
    private DbManager dbManager;
    private final int ACTION_REQUEST_PERMISSIONS = 0x001;

    private BroadcastReceiver mUsbPermissionActionReceiver;
    private final String ACTION_USB_PERMISSION = "com.jinbaoty.recyclebins.USB_PERMISSION";

    private static int cameraType = -1;
    private AlarmManagerUtils alarmManagerUtils;
    public static int getCameraType() {
        return cameraType;
    }

    public static void setCameraType(int cameraType) {
        MyApplication.cameraType = cameraType;
    }

    public static UsbDevice cameraDevice;

    private UsbSerialPort port;


    @Override
    public void onCreate() {
        super.onCreate();
        XUI.init(this); //初始化UI框架
        XUI.debug(true);  //开启UI框架调试日志
        x.Ext.init(this);
        x.Ext.setDebug(BuildConfig.DEBUG);
        Log.d("app版本", UpdateUtils.getVersionCode(this) + "");
        XUtil.init(this);
        XUtil.debug(true);
        initOKHttpUtils();
        XUpdate.get()
                .debug(false)
                .isWifiOnly(false)                                               //默认设置只在wifi下检查版本更新
                .isGet(true)                                                    //默认设置使用get请求检查版本
                .isAutoMode(false)                                              //默认设置非自动模式，可根据具体使用配置
                .param("versionCode", UpdateUtils.getVersionCode(this))         //设置默认公共请求参数
                .param("appKey", getPackageName())
                .setOnUpdateFailureListener(new OnUpdateFailureListener() {     //设置版本更新出错的监听
                    @Override
                    public void onFailure(UpdateError error) {
                        if (error.getCode() != CHECK_NO_NEW_VERSION) {          //对不同错误进行处理
                            ToastUtils.toast(error.toString());
                        }
                    }
                })
                .supportSilentInstall(false)                                     //设置是否支持静默安装，默认是true
                .setIUpdateHttpService(new OKHttpUpdateHttpService())           //这个必须设置！实现网络请求功能。
                .init(this);

        Logger.addLogAdapter(new AndroidLogAdapter());
        /*alarmManagerUtils = AlarmManagerUtils.getInstance(this);
        alarmManagerUtils.createGetUpAlarmManager();
        alarmManagerUtils.getUpAlarmManagerWorkOnOthers();*/
        initUseSerialPort();
        final Thread.UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(final Thread thread, final Throwable throwable) {
                //获取崩溃时的UNIX时间戳
                long timeMillis = System.currentTimeMillis();
                //将时间戳转换成人类能看懂的格式，建立一个String拼接器
                StringBuilder stringBuilder = new StringBuilder(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date(timeMillis)));
                stringBuilder.append(":\n");
                //获取错误信息
                stringBuilder.append(throwable.getMessage());
                stringBuilder.append("\n");
                //获取堆栈信息
                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw);
                throwable.printStackTrace(pw);
                stringBuilder.append(sw.toString());

                //这就是完整的错误信息了，你可以拿来上传服务器，或者做成本地文件保存等等等等
                String errorLog = stringBuilder.toString();
                Logger.d("崩溃日志：" + errorLog);

                //APIService.saveLog(errorLog);
                APIService.saveLog(errorLog, new StringCallback() {
                    @Override
                    public void onError(Call call, Exception e, int id) {

                    }

                    @Override
                    public void onResponse(String response, int id) {

                        //最后如何处理这个崩溃，这里使用默认的处理方式让APP停止运行
                        //defaultHandler.uncaughtException(thread, throwable);
                    }
                });


            }
        });
        //SAK.init(this, null);
        SqlScoutServer.create(this, getPackageName());
    }

    private void initUseSerialPort(){
        UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
        List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
        if (availableDrivers.isEmpty()) {

        }else{
            Logger.d("usb串口初始化，共找到%s个usb串口设备",availableDrivers.size());
            mUsbPermissionActionReceiver = new BroadcastReceiver() {
                public void onReceive(Context context, Intent intent) {
                    String action = intent.getAction();
                    if (ACTION_USB_PERMISSION.equals(action)) {
                        context.unregisterReceiver(this);//解注册
                        synchronized (this) {
                            UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                            if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                                if(null != usbDevice){
                                    Log.e("串口权限",usbDevice.getDeviceName()+"已获取USB权限");
                                }
                            }
                            else {
                                //user choose NO for your previously popup window asking for grant perssion for this usb device
                                Log.e("串口权限",String.valueOf("USB权限已被拒绝，Permission denied for device" + usbDevice));
                            }
                        }

                    }
                }
            };
            // Open a connection to the first available driver.
            UsbSerialDriver driver = availableDrivers.get(0);
            UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
            if (connection == null) {
                IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);

                if(mUsbPermissionActionReceiver != null) {
                    registerReceiver(mUsbPermissionActionReceiver, filter);
                }

                PendingIntent mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
                manager.requestPermission(driver.getDevice(),mPermissionIntent);
                return;
            }

            openPort(manager,driver);
            //开始扫描订单

        }
    }
    public void openPort(UsbManager manager,UsbSerialDriver driver){
        UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
        this.port = driver.getPorts().get(0); // Most devices have just one port (port 0)
        try {
            this.port.open(connection);
            this.port.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
            //serialPortTask = new CommandTask(this.port, serialStatusHandler);
            //new SerialInputOutputManager(this.port, serialPortTask);
            try {
                this.port.setDTR(true);
            }catch (IOException x){
                x.printStackTrace();
            }
            try {
                this.port.setRTS(true);
            }catch (IOException x){
                x.printStackTrace();
            }
            CommandParam[][] orderSet = CommandOrder.orderSet;
            for(int i=0;i<orderSet.length;i++){
                for(int j=0;j<orderSet[i].length;j++){
                    CommandParam commandParam = orderSet[i][j];
                    if (commandParam.getCommandTag().equals("close")) {
                        try {
                            long beginTime = System.currentTimeMillis();
                            if(this.port!=null) {
                                int write = port.write(new byte[]{commandParam.getCommandVal()}, 400);
                                byte[] buffer = new byte[20];
                                do {
                                    int readLen = this.port.read(buffer, commandParam
                                            .getReadTimeout());
                                    if (readLen > 0) {
                                        Logger.d(commandParam.getCommandName()+"，返回：" + new String(buffer, 0, readLen));
                                    }
                                }while(System.currentTimeMillis()-beginTime< commandParam.getReadTimeout());
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

            //new Thread(new ScanTask(this.port,serialStatusHandler)).start();
            //startScanOrder();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void initOKHttpUtils() {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(18000L, TimeUnit.MILLISECONDS)
                .readTimeout(18000L, TimeUnit.MILLISECONDS)
                .build();
        OkHttpUtils.initClient(okHttpClient);
    }

}
